package com.zhoust.fastdome.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;



/**
 * @author zhoust
 * @Date 2021/9/22 22:52
 * @Desc AOP 常用注解
 */
@Order(1)
@Slf4j
@Aspect
@Component
public class AspectDome {

    /**
     * 1、execution(): 表达式主体。
     * 2、第一个*号：表示返回类型， *号表示所有的类型。
     * 3、包名：表示需要拦截的包名，后面的两个句点表示当前包和当前包的所有子包，com.zhoust.fastdome.business.controller.scan包、子孙包下所有类的方法。
     * 4、第二个*号：表示类名，*号表示所有的类。
     * 5、*(..):最后这个星号表示方法名，*号表示所有的方法，后面括弧里面表示方法的参数，两个句点表示任何参数
     */
    @Pointcut("execution(* com.zhoust.fastdome.aspect.TestForAspectDomeController.*(..))")
    public void getPointCut(){
    }

    /**
     * 前置通知（Before）：在目标方法被调用之前调用通知功能
     * 后置通知（After）：在目标方法完成之后调用通知，此时不会关心方法的输出是什么
     * 返回通知（After-returning）：在目标方法成功执行之后调用通知
     * 异常通知（After-throwing）：在目标方法抛出异常后调用通知
     * 环绕通知（Around）：通知包裹了被通知的方法，在被通知的方
     * 法调用之前和之后执行自定义的行为
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("getPointCut()")
    public Object saveLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("=================Around 执行方法前，通过 joinPoint.proceed()执行方法==========================");
        // 执行目标 获取返回值（注意joinPoint.proceed()只能执行一次，执行多次就调用多次方法）
        Object result = joinPoint.proceed();
        log.info("=================Around 执行方法后，joinPoint.proceed() 的返回值就是执行结果==========================");
        return result;
    }
    @Before("getPointCut()")
    public void before(){
        log.info("==============Before 执行方法前执行==================");
    }
    @After("getPointCut()")
    public void after(){
        log.info("==============After 执行方法后执行，先于afterReturning==================");
    }

    @AfterReturning("getPointCut()")
    public void afterReturning(){
        log.info("==============afterReturning 执行方法后正常后执行==================");
    }
    @AfterThrowing("getPointCut()")
    public void afterThrowing(){
        log.info("==============AfterThrowing 方法执行异常后执行==================");
    }

}
